package junit;

import static org.junit.Assert.*;

import java.io.FileNotFoundException;
import java.io.IOException;
import org.junit.*;
import fast.CommandsEnum;
import fast.MasterProcessor;
import fast.SlaveProcessor;
import fast.TCPListener;
import fast.TCPTalker;
import fast.Buffer;

public class SlaveProcessorTest {
	
	private SlaveProcessor sp;
	private Buffer sendBuffer;
	private Thread sender;
	private Buffer listenBuffer;
	private Thread listener;
	
	public static void main(String[] args) throws FileNotFoundException, IOException{
		SlaveProcessorTest spt = new SlaveProcessorTest();
		
		spt.start_slave();
		spt.testSysPeer(); 			
		spt.testGetFile();  
		spt.testValidateFile();
		spt.testProcLoad();
		spt.testProcSearch();
		spt.testSysDone();		
		spt.testSysExit();		
		spt.testSysShut();	
//		spt.stop_slave(); 
	}

	
	// Method to test the Peering process.
	// This method sends the SYSTEM_PEER command and supplies an IP address for the master.
	private void testSysPeer() {
		try {
			System.out.print("\n  testSysPeer method.\n");
			sp.setMaster("");
			sendBuffer.add("127.0.0.1", 10001, 5, CommandsEnum.SYSTEM_PEER.toString(), "e");
		
			Thread.sleep(2000);
		
			assertEquals("Received Peer from Master Processor", sp.consoleOut);
		
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	// Test loading a valid file, includes several tests, 
	// 1	Loading the full file.
	// 2	Skipping the first few bytes.
	// 3	Skipping the first and last few bytes.
	// 4	Skipping the last few bytes.

	private void testGetFile() {
		try {
			System.out.print("\n  testGetFile method.\n");
			// Test loading the complete file.
			sp.getFile("/Users/Nick/Software/image.iso", 0, 7223296);
			
			// Test skipping the first few bytes.
			sp.getFile("/Users/Nick/Software/image.iso", 2048, 7221248);
			
			// Test skipping the first few and last few bytes.
			sp.getFile("/Users/Nick/Software/image.iso", 1024, 7218976);
			
			// Test skipping the last few bytes.
			sp.getFile("/Users/Nick/Software/image.iso", 0, 7189000);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace(); 
		}
		
	}


	// Test the Validate file method with a suitable file (image.iso) and an unsuitable file
	// wink-02k7e.bin.
	private void testValidateFile() {
		System.out.print("\n  testValidateFile method.\n");
		assertTrue(sp.validateFile("/Users/Nick/Software/image.iso"));
		
		assertFalse(sp.validateFile("/Users/Nick/Software/Windows/Microsoft Office 2007 Enterprise/" +
				"Microsoft Office 2007/wink-o2k7e.bin"));
	}

	
	// Test the searching algorithm with several search terms.
	private void testProcSearch() {
		
		System.out.print("\n  testProcSearch method.\n");

		sp.procSearch("README");

		assertTrue(sp.procSearch("test"));
		
		assertTrue(sp.procSearch("testing"));
		
		assertTrue(sp.procSearch("AHHHHHHHH"));

	}

	
	// Several File loading tests.
	public void testProcLoad(){
		
		System.out.print("\n  testProcLoad method.\n");
		
		// Test loading a file that is to big.
		sp.procLoad("/Users/Nick/Software/Windows/Microsoft Office 2007 Enterprise/" + 
				"Microsoft Office 2007/wink-o2k7e.bin,0,672624960" );
		assertFalse (sp.validateFile("/Users/Nick/Software/Windows/Microsoft Office 2007 Enterprise/" +
				"Microsoft Office 2007/wink-o2k7e.bin"));
		
		// Test loading a file that doesn't exist.
		sp.procLoad("/Users/Downloads/test.jpg,0,7223296" );
		assertFalse (sp.validateFile("/Users/Nick/Downloads/test.jpg"));
		
		// Test loading a part file. 
		sp.procLoad("/Users/Nick/Software/newtestimage.iso,0,7000296" );
		assertTrue(sp.validateFile("/Users/Nick/Software/image.iso"));
		
		// Test loading a part file. 
		sp.procLoad("/Users/Nick/Software/newtestimage.iso,3000000,7000000" );
		assertTrue(sp.validateFile("/Users/Nick/Software/image.iso"));
		
		// Test loading a part file. 
		sp.procLoad("/Users/Nick/Software/newtestimage.iso,3898998,7223296" );
		assertTrue(sp.validateFile("/Users/Nick/Software/image.iso"));
		
		// Test a valid full file.
		sp.procLoad("/Users/Nick/Software/newtestimage.iso,0,7223296" );
		assertTrue (sp.validateFile("/Users/Nick/Software/image.iso"));
		
	}
	
	
	// Test that the slave responds to a sysDone message from the Master.
	public void testSysDone(){
		System.out.print("\n  testSysDone method.\n");
	//send JOIN command to the slaveProcessor
			
	try {
		sendBuffer.add("127.0.0.1", 10001, 1, CommandsEnum.SYSTEM_DONE.toString(), "a");
	
		Thread.sleep(2000);
		
		assertEquals("Done 127.0.0.1 1 a", sp.consoleOut);
		

		
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	}


	// Test the SysExit method to ensure the slave exits.
	// Also resets the Slave MasterIP variable afterwards to allow further tests.
	public void testSysExit(){
		System.out.print("\n  testSysExit method.\n");
		try {
			sendBuffer.add("localhost", 10001, 2, CommandsEnum.SYSTEM_EXIT.toString(), "b");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			Thread.sleep(2000);
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		sp.setMaster("127.0.0.1");
	}
	
	
	// Test to shutdown the slave
	public void testSysShut(){
		System.out.print("\n  testSysShut method.\n");
		try {
			sendBuffer.add("localhost", 10001, 3, CommandsEnum.SYSTEM_SHUTDOWN.toString(), "c");
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	
	// Initialise the slaveProcessor, give a master IP address and start the listener, and sender.
	public void start_slave() throws FileNotFoundException, IOException{


		sp = new SlaveProcessor();
		sendBuffer  = new Buffer(10);
		sender = new Thread(new TCPTalker(sendBuffer));
		listenBuffer = new Buffer(10);
		listener = new Thread(new TCPListener(5000, listenBuffer));
		
		sp.setMaster("127.0.0.1");
		
		listener.start();
		sender.start();
		sp.start();
			
	}


//	// Stop and close the slave.
//	public void stop_slave(){
//		System.out.print("  stopSlave method.\n");
//	
//		System.exit(0);
//	}

	}